package com.titan.core.utils.data;


import java.io.ByteArrayOutputStream;
import java.io.PrintStream;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Locale;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.builder.ReflectionToStringBuilder;

import com.titan.core.utils.comm.SocketUtils;
import com.titan.core.utils.file.JsonUtils;
import com.titan.core.utils.io.ConsoleUtils;


/**
 * @author 周成功
 * @email 86898837@qq.com
 * @date 2020年02月10日
 */
public class FormatUtils {
    /**
     * 获取当前系统时间
     * 
     * @return java.util.Date
     */
    public static java.util.Date getSysdate() {
        return (new java.util.Date(System.currentTimeMillis()));
    }

    public static String getSysdate(String format) {
        return dateToString(getSysdate(), format);
    }
    
    
    public static String toString(Object object) {
        return toString(object, "");
    }

    public static String toString(Object object, String defaultValue) {
        return toString(object, "", defaultValue);
    }

    public static String toString(Object object, String format, String defaultValue) {
        if (object == null) {
            return defaultValue;
        } else if (object instanceof java.lang.String) {
            return (String)object;
        } else if (object instanceof java.lang.StringBuffer) {
            return ((StringBuffer)object).toString();
        } else if (object instanceof java.lang.StringBuilder) {
            return ((StringBuilder)object).toString();
        } else if (object instanceof java.math.BigDecimal) {
            if( (format==null)||(format.equals("")) ) {
                format = "0.######";
            }
            return numberToString((BigDecimal) object, format);
        } else if (object instanceof java.math.BigInteger) {
            if( (format==null)||(format.equals("")) ) {
                format = "0";
            }
            return numberToString((BigInteger) object, format);
        } else if (object instanceof java.lang.Boolean) {
            return ((Boolean) object).toString();
        } else if (object instanceof java.lang.Byte) {
            return ((Byte)object).toString();
        } else if (object instanceof java.lang.Character) {
            return ((Character)object).toString();
        } else if (object instanceof java.lang.Double) {
            if( (format==null)||(format.equals("")) ) {
                format = "0.######";
            }
            return numberToString(((Double) object).doubleValue(), format);
        } else if (object instanceof java.lang.Float) {
            if( (format==null)||(format.equals("")) ) {
                format = "0.######";
            }
            return numberToString(((Float) object).floatValue(), format);
        } else if (object instanceof java.lang.Short) {
            return numberToString(((Short) object).shortValue(), format);
        } else if (object instanceof java.lang.Long) {
            if( (format==null)||(format.equals("")) ) {
                format = "0";
            }
            return numberToString(((Long) object).longValue(), format);
        } else if (object instanceof java.lang.Integer) {
            if( (format==null)||(format.equals("")) ) {
                format = "0";
            }
            return numberToString(((Integer) object).intValue(), format);
        } else if (object instanceof java.util.Date) {
            if(StringUtils.isEmpty(format)) {
                format = "yyyy-MM-dd";
            }
            return dateToString((java.util.Date) object, format);
        } else if (object instanceof java.sql.Timestamp) {
            if(StringUtils.isEmpty(format)) {
                format = "yyyy-MM-dd HH:mm:ss";
            }
            return dateToString((java.sql.Timestamp) object, format);
        } else if (object instanceof java.util.Calendar) {
            if(StringUtils.isEmpty(format)) {
                format = "yyyy-MM-dd HH:mm:ss";
            }
            java.util.Calendar calendar = (java.util.Calendar)object;
            java.util.Date date = calendar.getTime();
            return dateToString(date, format);
        } else if (object instanceof java.nio.ByteBuffer) {
            java.nio.Buffer buffer = (java.nio.Buffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.DoubleBuffer) {
            java.nio.DoubleBuffer buffer = (java.nio.DoubleBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.FloatBuffer) {
            java.nio.FloatBuffer buffer = (java.nio.FloatBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.IntBuffer) {
            java.nio.IntBuffer buffer = (java.nio.IntBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.LongBuffer) {
            java.nio.LongBuffer buffer = (java.nio.LongBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.MappedByteBuffer) {
            java.nio.MappedByteBuffer buffer = (java.nio.MappedByteBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.ShortBuffer) {
            java.nio.ShortBuffer buffer = (java.nio.ShortBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof java.nio.CharBuffer) {
            java.nio.CharBuffer buffer = (java.nio.CharBuffer)object;
            return toStringByBuffer(buffer);
        } else if (object instanceof Throwable) {
            ByteArrayOutputStream array = null;
            PrintStream stream = null;
            try{
                array = new ByteArrayOutputStream();
                stream = new PrintStream(array);
                ((Throwable)object).printStackTrace(stream);
                //StringUtils.encodeHTML();
                return array.toString();
            } finally {
                SocketUtils.closeQuietly(stream);
                SocketUtils.closeQuietly(array);
            }
        } else if (object instanceof boolean[]
                || object instanceof byte[]
                || object instanceof char[]
                || object instanceof short[]
                || object instanceof int[]
                || object instanceof long[]
                || object instanceof float[]
                || object instanceof double[]
                || object instanceof Collection<?>
                || object.getClass().isArray()
                ) {
            return JsonUtils.toArrayString(object);
        } else if (object instanceof java.util.Map) {
            try {
                return JsonUtils.toString(object);
            } catch (Exception e) {
                return ReflectionToStringBuilder.toString(object);
            }
        } else if (object instanceof Class) {
            return ((Class)object).getName();
        } else if (java.net.InetAddress.class.isAssignableFrom(object.getClass())) {
            java.net.InetAddress instance = (java.net.InetAddress)object;
            return "{class:\""+object.getClass().getName()+"\", HostName:\""+instance.getHostName()+"\", HostAddress:\""+instance.getHostAddress()+"\", toString:\""+instance.toString()+"\"}";
        } else if (java.net.InetSocketAddress.class.isAssignableFrom(object.getClass())) {
            java.net.InetSocketAddress instance = (java.net.InetSocketAddress)object;
            return "{class:\""+object.getClass().getName()+"\", HostName:\""+instance.getHostName()+"\", Port:\""+instance.getPort()+"\", toString:\""+instance.toString()+"\"}";
        }
        return ReflectionToStringBuilder.toString(object);
    }
    private static String toStringByBuffer(java.nio.Buffer buffer) {
        if(buffer!=null && buffer.limit()>0 && buffer.hasArray()) {
            return JsonUtils.toArrayString(buffer.array());
        }
        return null;
    }

    
    /**
     * 将一个数值按照指定的格式转换成字符串型。
     * 
     * @param num
     *            double
     * @param format
     *            String
     * @return String
     */
    public static String numberToString(double num, String format) {
        if (format == null) {
            return Double.toString(num);
        }
        //NumberFormat fmt = NumberFormat.getInstance();
        NumberFormat fmt = new DecimalFormat(format, new DecimalFormatSymbols(Locale.getDefault()));
        fmt.setGroupingUsed(false);
        return fmt.format(num);
    }

    public static String numberToString(float num, String format) {
        return numberToString((double) num, format);
    }

    public static String numberToString(long num, String format) {
        return numberToString((double) num, format == null ? "0" : format);
    }

    public static String numberToString(int num, String format) {
        return numberToString((double) num, format == null ? "0" : format);
    }

    public static String numberToString(short num, String format) {
        return numberToString((double) num, format);
    }

    public static String numberToString(byte num, String format) {
        return numberToString((double) num, format);
    }    
    private static String objectToString(Object num, String format) {
        //NumberFormat fmt = NumberFormat.getInstance();
        NumberFormat fmt = new DecimalFormat(format, new DecimalFormatSymbols(Locale.getDefault()));
        fmt.setGroupingUsed(false);
        return fmt.format(num);
    }
    public static String numberToString(BigInteger num, String format) {
        return objectToString(num, format);
    }
    public static String numberToString(BigDecimal num, String format) {
        return objectToString(num, format);
    }    
    
    
    /**
     * 将一个日期型转换成指定的字符串
     * 
     * @param date
     *            Date
     * @param format
     *            String
     * @return String
     */
    public static String dateToString(java.util.Date date, String pattern) {
        return dateToString(date, pattern, null);
    }
    public static String dateToString(java.util.Date date, String pattern, Locale locale) {
        SimpleDateFormat sdf = toSimpleDateFormat(pattern, locale);
        return sdf.format(date);
    }
    public static String dateToString(java.sql.Timestamp times, String strFormat, Locale loc) {
        HashMap<String,Integer> _mapDateTimeStyle = new HashMap<String,Integer>(4);
        DateFormat fmt = null;
        _mapDateTimeStyle.put("FULL", new Integer(DateFormat.FULL));
        _mapDateTimeStyle.put("LONG", new Integer(DateFormat.LONG));
        _mapDateTimeStyle.put("MEDIUM", new Integer(DateFormat.MEDIUM));
        _mapDateTimeStyle.put("SHORT", new Integer(DateFormat.SHORT));
        Integer iDateStyle, iTimeStyle;
        int pos = strFormat.indexOf(",");
        if (pos == -1) {
            if (!_mapDateTimeStyle.containsKey(strFormat))
                fmt = new SimpleDateFormat(strFormat, loc);
            iDateStyle = iTimeStyle = (Integer) _mapDateTimeStyle.get(strFormat);
        } else {
            String strDateStyle = strFormat.substring(0, pos);
            String strTimeStyle = strFormat.substring(pos + 1);
            if (!_mapDateTimeStyle.containsKey(strDateStyle) || !_mapDateTimeStyle.containsKey(strTimeStyle))
                fmt = new SimpleDateFormat(strFormat, loc);
            iDateStyle = (Integer) _mapDateTimeStyle.get(strDateStyle);
            iTimeStyle = (Integer) _mapDateTimeStyle.get(strTimeStyle);
        }
        if (fmt == null) {
            fmt = DateFormat.getDateTimeInstance(iDateStyle.intValue(), iTimeStyle.intValue(), loc);
        }
        return fmt.format(times);
    }
    public static String dateToString(java.sql.Timestamp times, String strFormat) {
        return dateToString(times, strFormat, Locale.getDefault());
    }    
    
    public static java.util.Date stringToDate(String date, String format) {
        SimpleDateFormat sdf = toSimpleDateFormat(format);
        try {
            return sdf.parse(date);
        } catch (ParseException e) {
            ConsoleUtils.method(FormatUtils.class, "stringToDate", "date", date, "format", format, "exception", e.toString(), "sdf", sdf.toString());
            e.printStackTrace();
            throw new RuntimeException(e);
        } catch (NumberFormatException e) {
            ConsoleUtils.method(FormatUtils.class, "stringToDate", "date", date, "format", format, "exception", e.toString(), "sdf", sdf.toString());
            e.printStackTrace();
            throw e;
        }
    }    
    
    
    public static SimpleDateFormat toSimpleDateFormat(String pattern) {
        return toSimpleDateFormat(pattern, null);
    }
    public static SimpleDateFormat toSimpleDateFormat(String pattern, Locale locale) {
        Locale loc = (locale==null) ? Locale.SIMPLIFIED_CHINESE : locale;
        SimpleDateFormat formatter = new SimpleDateFormat(pattern, loc);
        return formatter;
    }
    
    public static String to2Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to3Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "00" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to4Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "00" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to5Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "0000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "000" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "00" + Long.toString(value);
        } else if( (value>=1000)&&(value<10000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to6Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "00000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "0000" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "000" + Long.toString(value);
        } else if( (value>=1000)&&(value<10000) ) {
            return "00" + Long.toString(value);
        } else if( (value>=10000)&&(value<100000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to7Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "000000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "00000" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "0000" + Long.toString(value);
        } else if( (value>=1000)&&(value<10000) ) {
            return "000" + Long.toString(value);
        } else if( (value>=10000)&&(value<100000) ) {
            return "00" + Long.toString(value);
        } else if( (value>=100000)&&(value<1000000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to8Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "0000000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "000000" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "00000" + Long.toString(value);
        } else if( (value>=1000)&&(value<10000) ) {
            return "0000" + Long.toString(value);
        } else if( (value>=10000)&&(value<100000) ) {
            return "000" + Long.toString(value);
        } else if( (value>=100000)&&(value<1000000) ) {
            return "00" + Long.toString(value);
        } else if( (value>=1000000)&&(value<10000000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to9Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "00000000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "0000000" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "000000" + Long.toString(value);
        } else if( (value>=1000)&&(value<10000) ) {
            return "00000" + Long.toString(value);
        } else if( (value>=10000)&&(value<100000) ) {
            return "0000" + Long.toString(value);
        } else if( (value>=100000)&&(value<1000000) ) {
            return "000" + Long.toString(value);
        } else if( (value>=1000000)&&(value<10000000) ) {
            return "00" + Long.toString(value);
        } else if( (value>=10000000)&&(value<100000000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }
    public static String to10Digit(Object number) {
        long value = FormatUtils.toLong(number);
        if( (value>=0)&&(value<10) ) {
            return "000000000" + Long.toString(value);
        } else if( (value>=10)&&(value<100) ) {
            return "00000000" + Long.toString(value);
        } else if( (value>=100)&&(value<1000) ) {
            return "0000000" + Long.toString(value);
        } else if( (value>=1000)&&(value<10000) ) {
            return "000000" + Long.toString(value);
        } else if( (value>=10000)&&(value<100000) ) {
            return "00000" + Long.toString(value);
        } else if( (value>=100000)&&(value<1000000) ) {
            return "0000" + Long.toString(value);
        } else if( (value>=1000000)&&(value<10000000) ) {
            return "000" + Long.toString(value);
        } else if( (value>=10000000)&&(value<100000000) ) {
            return "00" + Long.toString(value);
        } else if( (value>=100000000)&&(value<1000000000) ) {
            return "0" + Long.toString(value);
        } else {
            return Long.toString(value);
        }
    }    
    
    

    public static Boolean toBoolean(Object value) {
        if(value == null) {
            return null;
        }
        if ((value instanceof Boolean)) {
            return (Boolean)value;
        } else if (value instanceof com.titan.core.utils.object.Variant) {
            return ((com.titan.core.utils.object.Variant)value).getBoolean();
        }
        String var = toString(value, null, null);
        return (var.equals("1")) || (var.equals("-1")) 
            || (var.equalsIgnoreCase("t")) || (var.equalsIgnoreCase("true"))
            || (var.equalsIgnoreCase("y")) || (var.equalsIgnoreCase("yes"))
            || (var.equalsIgnoreCase("on")) || (var.equalsIgnoreCase("open"))
            ;
    }    
    public static Long toLong(Object value) {
        if (value == null) {
            return null;
        }
        if ((value instanceof Long)) {
            return (Long)value;
        } else if ((value instanceof Number)) {
            return ((Number)value).longValue();
        } else if ((value instanceof Boolean)) {
            return ((Boolean)value).booleanValue() ? 1L : 0L;
        } else if ((value instanceof Date)) {
            return ((Date)value).getTime();
        } else if (value instanceof com.titan.core.utils.object.Variant) {
            return ((com.titan.core.utils.object.Variant)value).getLong();
        }
        String var = toString(value, null, null);
        if (var.equals("")) {
            return null;
        }
        return Long.parseLong(var); 
    }
    public static Float toFloat(Object value) {
        if (value == null) {
            return null;
        }
        if ((value instanceof Float)) {
            return (Float)value;
        } else if ((value instanceof Number)) {
            return ((Number)value).floatValue();
        } else if ((value instanceof Boolean)) {
            return ((Boolean)value).booleanValue() ? 1.0F : 0.0F;
        } else if (value instanceof com.titan.core.utils.object.Variant) {
            return ((com.titan.core.utils.object.Variant)value).getFloat();
        }
        String var = toString(value, null, null);
        if (var.equals("")) {
            return 0.0F;
        }
        return Float.parseFloat(var);   
    }    
    public static Double toDouble(Object value) {
        if (value == null) {
            return null;
        }
        if ((value instanceof Double)) {
            return (Double)value;
        } else if ((value instanceof Number)) {
            return ((Number)value).doubleValue();
        } else if ((value instanceof Boolean)) {
            return ((Boolean)value).booleanValue() ? 1.0D : 0.0D;
        } else if (value instanceof com.titan.core.utils.object.Variant) {
            return ((com.titan.core.utils.object.Variant)value).getDouble();
        }
        String var = toString(value, null, null);
        if (var.equals("")) {
            return 0.0D;
        }
        return Double.parseDouble(var); 
    }    
    public static Date toDate(Object value) {
        if (value == null) {
            return null;
        }
//        ConsoleUtils.log("value", value, "getClass", value.getClass());
        if ((value instanceof Date)) {
            return new Date( ((Date)value).getTime() );
        } else if ((value instanceof Number)) {
            return new Date(((Number)value).longValue());
        } else if (value instanceof java.time.LocalDateTime) {
            java.time.LocalDateTime date = (java.time.LocalDateTime)value;
            java.time.ZoneId zone = java.time.ZoneId.systemDefault();
            java.time.Instant instant = date.atZone(zone).toInstant();
            return java.util.Date.from(instant);
        } else if (value instanceof java.time.LocalDate) {
            java.time.LocalDate date = (java.time.LocalDate)value;
            java.time.ZoneId zone = java.time.ZoneId.systemDefault();
            java.time.Instant instant = date.atStartOfDay().atZone(zone).toInstant();
            return java.util.Date.from(instant);
        } else if (value instanceof java.time.LocalTime) {
            java.time.LocalTime localTime = (java.time.LocalTime)value;
            java.time.LocalDate localDate = java.time.LocalDate.now();
            java.time.LocalDateTime localDateTime = java.time.LocalDateTime.of(localDate, localTime);
            java.time.ZoneId zone = java.time.ZoneId.systemDefault();
            java.time.Instant instant = localDateTime.atZone(zone).toInstant();
            return java.util.Date.from(instant);
        } else if (value instanceof com.titan.core.utils.object.Variant) {
            return ((com.titan.core.utils.object.Variant)value).getDate();
        } else if ( value instanceof String ) {
            String date = String.valueOf(value);
            if (date.equals("")) {
                return null;
            }       
            try {
                DateUtils util = DateUtils.$Min(date);
                return util.getDate();
            } catch (ParseException e) {
                e.printStackTrace();
            }
        }
        return null;
    }    
    
    
    
}
